App.require(function () {
    var app = App.getCurrent();
    var waitList = [];

    function pushImage(obj) {
        waitList.push(obj);
        if (waitList.length > 0) window.addEventListener("scroll", scrollHandler, false);
    }

    function sliceImage(id) {
        for (var i = waitList.length - 1; i >= 0; i--) {
            if (waitList[i].id === id) return waitList.splice(i, 1);
        }
        if (waitList.length == 0) window.removeEventListener("scroll", scrollHandler, false);
    }

    function isInView(dom) {
        var box = dom.getBoundingClientRect();
        return !(box.left > window.innerWidth || box.right < 0 || box.top > window.innerHeight || box.bottom < 0);
    }

    function attachImgProperty(component) {
        var img = document.createElement("img");
        var property = component.property;
        if (property.class) img.className = property.class;
        ["src", "alt", "srcset", "sizes", "width", "height", "title", "crossorigin"].forEach(function (item) {
            if (property[item]) img[item] = property[item];
        });
        component.addDomEventListener("img", img, "load", component.loadHandler, false)
            .addEventListener("img", "error", component.errorHandler, false)
            .addEventListener("img", "click", component.clickImgHandler, false);
        component.data.loaded = true;
        component.nodes[0] = img;
    }


    function scrollHandler(ev) {
        for (var i = waitList.length - 1; i >= 0; i--) {
            var obj = waitList[i];
            if (!obj.component.data.loaded && obj.component.domList.div && isInView(obj.component.domList.div)) {
                attachImgProperty(obj.component);
                waitList.splice(i, 1);
            } 
        }
        if (waitList.length == 0) window.removeEventListener("scroll", scrollHandler, false);
    }

    app.defineComponent("str-img", {
        render: function (next) {
            this.computeData();
            this.fetch("index.html", function (text) {
                return next(this.renderHTML(text));
            })
        },
        getDomObj: function () {
            this.attachDom("div", "div")
                .attachDiyEvent("enterend", this.enterEndHandler);
        },
        clickImgHandler: function (ev) {
            var event = this.getCanCancelEvent();
            this.dispatchCustomEvent("imgclick", {
                component: this,
                event: event,
                originEvent: ev
            });
            if (this.property.popup) {
                if (!event.isCancel) {
                    ev.preventDefault();
                    ev.stopPropagation();
                    app.showImgViewer([{ title: "图片", url: this.property.src }]);
                }
            }
        },
        _errorHandler: function (ev) {
            var event = this.getCanCancelEvent();
            this.dispatchCustomEvent("imgerror", {
                component: this,
                event: event
            });
            if (!event.isCancel) {
                this.domList.img.src = "/public/ui/img/qst.png";
            }
        },
        _loadHandler: function (ev) {
            if (this.domList.div) this.domList.div.parentNode.replaceChild(ev.target, this.domList.div);
            this.domList.div = null;
            this.dispatchCustomEvent("imgload", {
                component: this,
                event: ev
            });
        },
        dispose: function () {
            sliceImage(this.uid);
        },
        enterEndHandler: function () {
            var that = this;
            if (that.domList.div) {
                if (isInView(that.domList.div) && !that.data.loaded) {
                    attachImgProperty(that);
                }
                else {
                    pushImage({
                        id: that.uid,
                        src: that.property.src,
                        component: that
                    });
                }
            }
            that.timeId = null;
        },
        init: function () {
            this.loadHandler = this._loadHandler.bind(this);
            this.errorHandler = this._errorHandler.bind(this);
            if (this.property.show) attachImgProperty(this);
        },
        dispose: function () {
            if (this.timeId) clearTimeout(this.timeId);
        },
        computeData: function () {
            var property = this.property;
            property.class = property.class || "";
            property.src = property.src || "";
            property.alt = property.alt || "";

            property.srcset = property.srcset || "";
            property.sizes = property.sizes || "";
            property.width = property.width || "";
            property.height = property.height || "";
            property.title = property.title || "";
            property.crossorigin = property.crossorigin || "";
            property.popup = typeof property.popup !== "undefined" ? "show": "";
            property.show = typeof property.show !== "undefined" ? "show": "";
        },
        get show() {
            return this.property.show;
        },
        set show(value) {
            value = value ? "show": "";
            if (value === this.property.show) return;
            this.property.show = value;
        },
        get popup() {
            return this.property.popup;
        },
        set popup(value) {
            value = value ? "show": "";
            if (value === this.property.popup) return;
            this.property.popup = value;
        },
        get crossorigin() {
            return this.property.crossorigin;
        },
        set crossorigin(value) {
            if (value === this.property.crossorigin) return;
            if (this.data.loaded) this.domList.img.crossorigin = value;
            this.property.crossorigin = value;
        },
        get title() {
            return this.property.title;
        },
        set title(value) {
            if (value === this.property.title) return;
            if (this.data.loaded) this.domList.img.title = value;
            this.property.title = value;
        },
        get height() {
            return this.property.height;
        },
        set height(value) {
            if (value === this.property.height) return;
            if (this.data.loaded) this.domList.img.height = value;
            this.property.height = value;
        },
        get width() {
            return this.property.width;
        },
        set width(value) {
            if (value === this.property.width) return;
            if (this.data.loaded) this.domList.img.width = value;
            this.property.width = value;
        },
        get sizes() {
            return this.property.sizes;
        },
        set sizes(value) {
            if (value === this.property.sizes) return;
            if (this.data.loaded) this.domList.img.sizes = value;
            this.property.sizes = value;
        },
        get srcset() {
            return this.property.srcset;
        },
        set srcset(value) {
            if (value === this.property.srcset) return;
            if (this.data.loaded) this.domList.img.srcset = value;
            this.property.srcset = value;
        },
        set alt(value) {
            if (this.property.alt === value) return;
            if (this.data.loaded) this.domList.img.alt = value;
            this.property.alt = value;
        },
        get alt() {
            return this.property.alt;
        },
        set src(value) {
            if (value === this.property.src) return;
            if (this.data.loaded) this.domList.img.src = value;
            this.property.src = value;
        },
        get src() {
            return this.property.src;
        },
        set className(value) {
            if (this.property.class === value) return;
            var dom = this.data.loaded ? this.domList.img : this.domList.div;
            dom.className = value;
            this.property.class = value;
        },
        get className() {
            return this.property.class;
        }
    })
})